package papers

import (
	"bufio"
	"fmt"
	"images-bed/config"
	"os"
	"sync"
)

// Papers 文件系统
type Papers struct {
	BasePath    string `json:"BasePath"`
	MaxFileSize uint64 `json:"MaxFileSize"`
}

// NewPapers 构造一个文件系统
func NewPapers(BasePath string, MaxFileSize uint64) *Papers {

	var need bool = false
	stat, err := os.Stat(BasePath)
	// 文件夹不存在
	if err != nil {
		if os.IsNotExist(err) {
			need = true
		}
	} else {
		// 如果存在，判断是否为文件夹，只有是文件的时候创建文件夹
		if !stat.IsDir() {
			need = true
		}
	}

	// 如果需要，则创建
	if need {
		err := os.MkdirAll(BasePath, 0644)
		if err != nil {
			return nil
		}
	}

	papers := new(Papers)
	papers.BasePath = BasePath
	papers.MaxFileSize = MaxFileSize
	return papers
}

// Path 目录
type Path struct {
	Scene string `json:"scene"`
	Year  int    `json:"year"`
	Month int    `json:"month"`
	Day   int    `json:"day"`
}

// Paper 文件
type Paper struct {
	Path    Path   `json:"path"`
	PaperId string `json:"PaperId"`
	Name    string `json:"name"`
	Suffix  string `json:"suffix"`
}

// PathAddr 获取路径真实路径
func (papers *Papers) PathAddr(path Path) string {
	addr := fmt.Sprintf("%s/%s/%d/%d/%d/", papers.BasePath, path.Scene,
		path.Year, path.Month, path.Day)
	return addr
}

// PaperAddr 获取文件的真实地址
func (papers *Papers) PaperAddr(paper Paper) string {
	var addr string
	path := papers.PathAddr(paper.Path)
	stat, errExist := os.Stat(path)
	if errExist == nil && stat.IsDir() {
		addr = path + paper.PaperId + "-" + paper.Name + "." + paper.Suffix
		return addr
	} else {
		return ""
	}
}

// Reader 读对象
type Reader struct {
	File   *os.File
	Reader *bufio.Reader
}

// Writer 写对象
type Writer struct {
	File   *os.File
	Writer *bufio.Writer
}

// OpenPaperReader 打开文件读取流
func (papers *Papers) OpenPaperReader(paper Paper) *Reader {
	if papers.PathCreate(paper.Path) {
		addr := papers.PaperAddr(paper)
		if addr != "" {
			file, err := os.Open(addr)
			if err != nil {
				return nil
			}
			return &Reader{file, bufio.NewReader(file)}
		} else {
			return nil
		}
	} else {
		return nil
	}
}

// OpenPaperAppender 打开追加
func (papers *Papers) OpenPaperAppender(paper Paper) *Writer {
	if papers.PathCreate(paper.Path) {
		addr := papers.PaperAddr(paper)
		if addr != "" {
			file, err := os.OpenFile(addr, os.O_APPEND|os.O_CREATE, 0644)
			if err != nil {
				return nil
			}
			return &Writer{file, bufio.NewWriter(file)}
		} else {
			return nil
		}
	} else {
		return nil
	}
}

// OpenPaperWriter 打开文件创建
func (papers *Papers) OpenPaperWriter(paper Paper) *Writer {
	if papers.PathCreate(paper.Path) {
		addr := papers.PaperAddr(paper)
		if addr != "" {
			file, err := os.OpenFile(addr, os.O_TRUNC|os.O_CREATE, 0644)
			if err != nil {
				return nil
			}
			return &Writer{file, bufio.NewWriter(file)}
		} else {
			return nil
		}
	} else {
		return nil
	}
}

// PathCreate 创建路径
func (papers *Papers) PathCreate(path Path) bool {
	var need bool = false
	addr := papers.PathAddr(path)
	stat, errExist := os.Stat(addr)
	if errExist != nil {
		if os.IsNotExist(errExist) {
			need = true
		}
	} else {
		if !stat.IsDir() {
			need = false
		}
	}

	if need {
		err := os.MkdirAll(addr, 0644)
		if err != nil {
			return false
		}
		return true
	} else {
		return true
	}
}

// CloseWriterPaper 关闭文件
func (papers *Papers) CloseWriterPaper(writer *Writer) {
	err := writer.File.Close()
	if err != nil {
		return
	}
}

// CloseReaderPaper 关闭文件
func (papers *Papers) CloseReaderPaper(reader *Reader) {
	err := reader.File.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
}

//////////////////////////////////////////////////////

var (
	single *Papers
	once   sync.Once
)

// 初始化文件系统
func InitPapers() bool {

	if config.GetConfig().BasePath == "" ||
		config.GetConfig().MaxFileSize <= 0 {
		return false
	}

	once.Do(func() {
		// 初始化单例文件系统
		single = NewPapers(
			config.GetConfig().BasePath,
			config.GetConfig().MaxFileSize,
		)
	})

	return true
}

func GetPapers() *Papers {
	return single
}
